package com.deer.wms.ASN.manage.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.deer.wms.ASN.manage.constant.AsnManageConstant;
import com.deer.wms.ASN.manage.dao.QcRecordMapper;
import com.deer.wms.ASN.manage.model.in.AcceptRecord;
import com.deer.wms.ASN.manage.model.qc.*;
import com.deer.wms.ASN.manage.service.AcceptRecordService;
import com.deer.wms.ASN.manage.service.QcRecordFileService;
import com.deer.wms.ASN.manage.service.QcRecordService;
import com.deer.wms.intercept.common.data.CurrentUser;
import com.deer.wms.inventory.constant.InventoryConstant;
import com.deer.wms.inventory.model.Inventory.*;
import com.deer.wms.inventory.service.InventoryService;
import com.deer.wms.inventory.service.InventoryTransactService;
import com.deer.wms.inventory.util.ExportExcelUtils;
import com.deer.wms.project.root.core.result.CommonCode;
import com.deer.wms.project.root.exception.ServiceException;
import com.deer.wms.project.root.service.SuperServiceImpl;
import com.deer.wms.project.root.util.BeanUtils;
import com.deer.wms.project.root.util.DateUtils;
import com.deer.wms.system.manage.constant.SystemManageConstant;
import com.deer.wms.system.manage.service.CodeRuleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author guo
 * @since 2020/01/15
 */
@Service
@Transactional
public class QcRecordServiceImpl extends SuperServiceImpl<QcRecordMapper, QcRecord> implements QcRecordService {

    @Autowired
    private QcRecordMapper qcRecordMapper;
    @Autowired
    private QcRecordService qcRecordService;
    @Autowired
    private QcRecordFileService qcRecordFileService;
    @Autowired
    private AcceptRecordService acceptRecordService;
    @Autowired
    private CodeRuleService codeRuleService;
    @Autowired
    private InventoryTransactService inventoryTransactService;
    @Autowired
    private InventoryService inventoryService;


    @Override
    public void exportExcel(HttpServletResponse response, String keyWords, String asnMasterCode, String acceptRecordCode, String batchName,  String startTime, String endTime) throws Exception {
        ExcelData data = new ExcelData();
        data.setName("质检记录");//sheet表名称
        //表头
        List<String> titles = new ArrayList();
        titles.add("序号");
        titles.add("单据号");
        titles.add("入库任务号");
        titles.add("收货单号");
        titles.add("物料编码");
        titles.add("物料名称");
        titles.add("批次号");
        titles.add("质检数量");
        titles.add("合格数量");
        titles.add("不合格数量");
        titles.add("合格率");
        titles.add("质检员");
        titles.add("质检时间");
        titles.add("备注");
        data.setTitles(titles);
        List<List<Object>> rows = new ArrayList();
        //添加查询条件
        QcRecordCriteria criteria = new QcRecordCriteria();
        criteria.setAcceptRecordCode(acceptRecordCode);
        criteria.setAsnMasterCode(asnMasterCode);
        criteria.setBatchName(batchName);
        criteria.setStartTime(startTime);
        criteria.setEndTime(endTime);
        criteria.setKeyWords(keyWords);
        criteria.setPageNum(1);
        criteria.setPageSize(999999);
        //调用查询方法
        List<QcRecordDto> returnList = findList(criteria);
        //封装数据
        rows = getRow(returnList);
        data.setRows(rows);
        ExportExcelUtils.exportExcel(response,"库存记录.xlsx",data);
    }

    private List<List<Object>> getRow(List<QcRecordDto> returnList){
        List<List<Object>> rows = new ArrayList();
        if (returnList.size()>0){
            for (int i=0;i<returnList.size();i++){
                List<Object> row = new ArrayList();
                row.add(i+1);
                row.add(returnList.get(i).getQcRecordCode());
                row.add(returnList.get(i).getAsnMasterCode());
                row.add(returnList.get(i).getAcceptRecordCode());
                row.add(returnList.get(i).getItemCode());
                row.add(returnList.get(i).getItemName());
                row.add(returnList.get(i).getBatchName());
                row.add(returnList.get(i).getQcQuantity());
                row.add(returnList.get(i).getQualifiedQuantity());
                row.add(returnList.get(i).getFiedQuantity());
                row.add(returnList.get(i).getOne()+"%");
                row.add(returnList.get(i).getQcUserName());
                row.add(returnList.get(i).getQcTime());
                row.add(returnList.get(i).getMemo());
                rows.add(row);
            }
        }
        return rows;
    }

    @Override
    public List<QcRecordDto> findList(QcRecordCriteria criteria) {
        return qcRecordMapper.findList(criteria);
    }

    @Override
    public List<QcRecordDto> findReturnList(QcRecordCriteria criteria) {
        return qcRecordMapper.findReturnList(criteria);
    }

    /**
     * 归档
     *
     * @param detailNo
     * @param currentUser
     */
    @Override
    public void createFile(String detailNo, CurrentUser currentUser) {
        QcRecord qcRecord = qcRecordService.getOneByField("detail_no", detailNo);

        Integer fileUserId = currentUser.getUserId();
        String fileUserName = currentUser.getUserName();
        String fileTime = DateUtils.getNowDateTimeString();

        QcRecordFile qcRecordFile = new QcRecordFile();
        BeanUtils.copyProperties(qcRecordFile, qcRecord);

        qcRecordFile.setCreateUserId(fileUserId);
        qcRecordFile.setCreateUserName(fileUserName);
        qcRecordFile.setCreateTime(fileTime);

        qcRecordFileService.save(qcRecordFile);
        qcRecordService.deleteByDetailNo(detailNo);
    }

    @Override
    public void deleteByDetailNo(String detailNo) {
        qcRecordMapper.deleteByDetailNo(detailNo);
    }

    @Override
    public void cancelNQ(String qcRecordCode,CurrentUser currentUser){
        //查出质检单
        QcRecord qcRecord=qcRecordService.getOneByField("qc_record_code",qcRecordCode);
        if(qcRecord.getQualifiedQuantity() > 0.0){
            throw new ServiceException(CommonCode.CUSTOMER_EXISTS, "请选择不合格的质检记录");
        }
        //查出该收货单对应的库存记录
        //根据收货单号去查库存修改库存
        List<Inventory> list = inventoryService.getListByField("bill_no",qcRecord.getAcceptRecordCode());
        //删除不合格库存
        if(list.size() > 0){
            for(Inventory inventory:list){
                inventoryService.removeById(inventory);
            }
        }
    }
    @Override
    public void cancelQc(String qcRecordCode,CurrentUser currentUser){
        //查出质检单
        QcRecord qcRecord=qcRecordService.getOneByField("qc_record_code",qcRecordCode);
        //查出对应的收货单
        AcceptRecord acceptRecord = acceptRecordService.getOneByField("accept_record_code",qcRecord.getAcceptRecordCode());
        //当原单据已经质检完毕
        if(acceptRecord.getQcState().equals(2)){
            //设置为待检
            acceptRecord.setQcState(1);
        }
        //不合格数量
        acceptRecord.setUnqualifiedQuantity(0.0);
        acceptRecord.setQualifiedQuantity(0.0);
        //根据收货单号去查库存修改库存
        List<Inventory> list = inventoryService.getListByField("bill_no",acceptRecord.getAcceptRecordCode());
         if(list.size() == 0){
             throw new ServiceException(CommonCode.CUSTOMER_EXISTS, "该记录已被确认不合格操作!无法进行撤销!");
         }
        List<Inventory> inv=new ArrayList<>();
        for(Inventory inventory:list){
            if(!inventory.getQuantity().equals(0.0)){
                inventory.setFreezeQuantity(inventory.getQuantity());
            }
            if(!inventory.getFreezeQuantity().equals(0.0)){
                inventory.setQuantity(inventory.getFreezeQuantity());
            }
            //冻结库存
            inventory.setState(1);
            //收货库位
            inventory.setCellCode("286000");
            inventory.setStateDis("待检");
            inv.add(inventory);
        }
//        Inventory inventory = inventoryService.getById(acceptRecord.getInventoryId());
//            //冻结库存加上质检原数量
//            inventory.setFreezeQuantity(inventory.getFreezeQuantity() + qcRecord.getQcQuantity());
//            //库存数量撤回
//            inventory.setQuantity(inventory.getQuantity() - qcRecord.getQualifiedQuantity());
//            inventory.setState(InventoryConstant.TRANSACT_STATE_NORMAL);
//            if (inventory.getQuantity().equals(0.0)) {
//                //冻结库存
//                inventory.setState(InventoryConstant.TRANSACT_STATE_UNNORMAL);
//            }
            acceptRecordService.updateById(acceptRecord);
            inventoryService.saveOrUpdateBatch(inv);
            qcRecordService.removeById(qcRecord);
    }
    @Override
    public QcRecord qcResult(QcResultCriteria criteria, CurrentUser currentUser) {
        //Step1.根据收货单生成质检单
        AcceptRecord acceptRecord = acceptRecordService.getOneByField("accept_record_code", criteria.getBillCode());
        Double qualifiedQuantity = criteria.getQualifiedQuantity();
        Double fiedQuantity = criteria.getFiedQuantity();
        //需要判断是否已质检
        if (ObjectUtil.equal(AsnManageConstant.ACCEPT_QC_STATE_FINISH, acceptRecord.getQcState())) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "收货单：" + acceptRecord.getAcceptRecordCode() + "已质检");
        }
        QcRecord qcRecord = processQcData(acceptRecord, currentUser);
        qcRecord.setQcRecordCode(codeRuleService.generateCode(SystemManageConstant.CORE_RULE_QC));
        // 设置合格，不合格，让步数量 质检结果 质检时间
        qcRecord.setQualifiedQuantity(qualifiedQuantity);
        qcRecord.setFiedQuantity(fiedQuantity);
        qcRecord.setConcessionQuantity(0.0);
        qcRecord.setQcQuantity(qualifiedQuantity + fiedQuantity);
        qcRecord.setMemo(criteria.getMemo());
        qcRecordService.save(qcRecord);

        //Step2.生成库存事务 操作库存
        InventoryTransact inventoryTransact = toStockRequest(qcRecord);
        // 先拆分 后质检 质检后需要去查收货单对应的全部库存记录
        List<Inventory> list = inventoryService.getListByField("bill_no",acceptRecord.getAcceptRecordCode());
        List<Inventory> inv=new ArrayList<>();
        for(Inventory inventory:list){
            //判定为不合格
            if (fiedQuantity > 0.0) {
              //将库存转移到不合格库位上面去
                inventory.setFreezeQuantity(inventory.getQuantity());
                //不合格货位
                inventory.setCellCode("zp-NQ01");
                //不合格库存
                inventory.setState(1);
                inventory.setStateDis("不合格");
            }else{
                inventory.setQuantity(inventory.getQuantity());
                //不合格数量等于合格数量
                inventory.setFreezeQuantity(0.0);
                inventory.setState(0);
                inventory.setStateDis("已检");
            }
            inv.add(inventory);
        }
        inventoryService.saveOrUpdateBatch(inv);
        Inventory inventory = inventoryService.getById(acceptRecord.getInventoryId());
        //删除负库存
        inventoryService.removeById(inventory);
//        if (qualifiedQuantity > 0.0) {
//            //冻结库存减去合格数量 也要减去不合格数量  不合格数量不占用冻结库存
//            inventory.setFreezeQuantity(inventory.getFreezeQuantity() - qualifiedQuantity - fiedQuantity);
//            inventory.setQuantity(inventory.getQuantity() + qualifiedQuantity);
//            inventory.setState(InventoryConstant.TRANSACT_STATE_NORMAL);
//            if (inventory.getFreezeQuantity().equals(0.0)) {
//                inventory.setStateDis(null);
//            }
//            inventoryService.saveOrUpdate(inventory);
//        }

        //Step3.更新收货单（合格数量、不合格数量）
        acceptRecord.setQualifiedQuantity(acceptRecord.getQualifiedQuantity() + qualifiedQuantity);
        acceptRecord.setUnqualifiedQuantity(acceptRecord.getUnqualifiedQuantity() + fiedQuantity);
        if (acceptRecord.getQuantity() == (acceptRecord.getQualifiedQuantity()+acceptRecord.getUnqualifiedQuantity())) {
            acceptRecord.setQcState(AsnManageConstant.ACCEPT_QC_STATE_FINISH);
        }
        acceptRecordService.updateById(acceptRecord);

        return qcRecord;
    }

    @Override
    public void returnConfirm(List<QcRecord> qcRecords) {
        for (QcRecord qcRecord : qcRecords) {
            //退料数量
            double returnQty = qcRecord.getFiedQuantity() - qcRecord.getConcessionQuantity();
            //让步数量
            Double concessionQuantity = qcRecord.getConcessionQuantity();

            Inventory inv = inventoryService.getById(qcRecord.getInventoryId());
            inv.setQuantity(inv.getQuantity() + concessionQuantity);
            inv.setFreezeQuantity(inv.getFreezeQuantity() - returnQty - concessionQuantity);
            if (inv.getFreezeQuantity() == 0.0 && inv.getQuantity() == 0) {
                //不合格数量等于冻结数量，说明库存全部扣减
                inventoryService.removeById(inv);
            } else {
                if (inv.getQuantity() > 0.0) {
                    inv.setState(InventoryConstant.TRANSACT_STATE_NORMAL);
                    inv.setStateDis(null);
                }
                inventoryService.updateById(inv);
            }

            AcceptRecord acceptRecord = acceptRecordService.getById(qcRecord.getAcceptRecordId());
            acceptRecord.setUnqualifiedQuantity(acceptRecord.getUnqualifiedQuantity() - concessionQuantity);
            acceptRecord.setQualifiedQuantity(acceptRecord.getQualifiedQuantity() + concessionQuantity);
            acceptRecordService.updateById(acceptRecord);

            qcRecord.setReturnState(1);
        }
        qcRecordService.updateBatchById(qcRecords);
        //这里要传接口  保持数据一致
    }

    @Override
    public void concession(Map<Integer, Double> map) {
        List<QcRecord> qcRecords = new ArrayList<>();
        for (Integer qcId : map.keySet()) {
            QcRecord qcRecord = this.getById(qcId);
            Double concessionQty = map.get(qcId);
            qcRecord.setConcessionQuantity(concessionQty);
            qcRecords.add(qcRecord);
        }
        this.updateBatchById(qcRecords);
    }

    /**
     * 根据质检单生成库存事务
     *
     * @param qcRecord 质检单
     * @return InventoryTransact 库存事务
     */
    private InventoryTransact toStockRequest(QcRecord qcRecord) {
        InventoryTransact inventoryTransact = new InventoryTransact();
        //Step1.准备数据
        //仓库
        inventoryTransact.setWareId(qcRecord.getWareId());
        inventoryTransact.setWareName(qcRecord.getWareName());
        //物料
        inventoryTransact.setItemCode(qcRecord.getItemCode());
        inventoryTransact.setItemName(qcRecord.getItemName());
        //批次
        inventoryTransact.setFromBatchId(qcRecord.getBatchId());
        inventoryTransact.setFromBatchName(qcRecord.getBatchName());
        //创建人 时间
        inventoryTransact.setCreateUserId(qcRecord.getQcUserId());
        inventoryTransact.setCreateUserName(qcRecord.getQcUserName());
        inventoryTransact.setCreateTime(DateUtil.now());
        //事务类型
        inventoryTransact.setTransactType(InventoryConstant.TRANSACT_TYPE_QC);
        //来源单据号
        inventoryTransact.setBillNo(qcRecord.getQcBillNo());
        inventoryTransact.setFromQuantity(qcRecord.getQualifiedQuantity());
        inventoryTransact.setToQuantity(qcRecord.getFiedQuantity());

        inventoryTransact.setBillNo(qcRecord.getQcRecordCode());
        //Step2.保存，返回
        inventoryTransactService.save(inventoryTransact);
        return inventoryTransact;
    }

    /**
     * 生成质检单
     *
     * @param acceptRecord 收货单
     * @return QcRecord
     */
    private QcRecord processQcData(AcceptRecord acceptRecord, CurrentUser currentUser) {
        QcRecord qcRecord = new QcRecord();
        //来源单号
        qcRecord.setAcceptRecordId(acceptRecord.getId());
        qcRecord.setAcceptRecordCode(acceptRecord.getAcceptRecordCode());
        //仓库
        qcRecord.setWareId(acceptRecord.getWareId());
        qcRecord.setWareName(acceptRecord.getWareName());
        //物料
        qcRecord.setItemCode(acceptRecord.getItemCode());
        qcRecord.setItemName(acceptRecord.getItemName());
        qcRecord.setPackDetailId(acceptRecord.getPackDetailId());
        qcRecord.setPackDescribe(acceptRecord.getPackDescribe());
        //批次
        qcRecord.setBatchId(acceptRecord.getBatchId());
        qcRecord.setBatchName(acceptRecord.getBatchName());
        //数量
        qcRecord.setAsnDetailCode(acceptRecord.getAsnDetailNo());
        qcRecord.setAsnMasterCode(acceptRecord.getAsnBillNo());

        qcRecord.setInventoryId(acceptRecord.getInventoryId());

        qcRecord.setQcTime(DateUtil.now());
        qcRecord.setQcUserId(currentUser.getUserId());
        qcRecord.setQcUserName(currentUser.getUserName());

        qcRecord.setReturnState(0);

        return qcRecord;
    }

}
